home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / Documentation / Engineering Notes / Views / Using List Boxes < prev   
Encoding:
Text File  |  1996-04-26  |  17.8 KB  |  311 lines  |  [TEXT/ttxt]

  1. OpenDoc
  2. Development
  3. Framework
  4.                                                                                                                                                                                             
  5. Using List Boxes 
  6. ODF Release 1                                                                                                                                                                     
  7.  
  8.  
  9.  
  10. Table of Contents
  11. -------------------------
  12. • Introduction
  13. • Adding a List Box to Your Frame
  14. • FW_CListBox Reference
  15. • Adding More Features to FW_CListBox
  16. • Miscellaneous Issues
  17.  
  18.  
  19. Introduction
  20.  
  21. This document explains how to use FW_CListBox to implement list views in your part.  FW_CListBox is a wrapper for Macintosh scrollable lists implemented by the List Manager, see Inside Macintosh “More Macintosh Toolbox”.  It is well suited for simple 1 column list boxes.   If your part requires lists or tables displaying non-string items, large amounts of data, or  multiple columns, you need to implement them yourself.  
  22.  
  23. The features and limitations of FW_CListBox in the current release are the following:
  24. • 1 column only, with or without vertical scroll bar.
  25. • A second invisible “client data” column lets you store 4 bytes values in each row.
  26. • Items are strings up to 255 characters.  Font can be changed but there is no custom drawing of other data.
  27. • No more than 32K of total data (for instance, 1600 rows of 20 character strings).
  28. • Single or multiple selection mode.
  29. • Navigation and selection by keyboard.
  30. • Auto-scrolling.
  31. • The active list box can be outlined with a frame.
  32. • Selecting an item with a double-click sends a  notification to the list’s receivers.
  33. • Extra work is required to display a list box across multiple facets or multiple frames (see Issues at the end).
  34.  
  35. ODF Form shows an example of a list box view.  Run it and look at the source code in ODFDev:Form:Sources.
  36.  
  37. ODF Table is not an example of a multi-column list view, it displays a grid of cells where other parts can be embedded.
  38.  
  39.  
  40. Adding a List Box to Your Frame
  41.  
  42. Creation by Program or by Resource
  43.  
  44. When creating a list box by program, use the 1-step initialization class constructor:
  45.  
  46.     FW_CListBox(Environment* ev, 
  47.                       FW_CSuperView* container,
  48.                       const FW_CRect& bounds,
  49.                       ODID viewId,
  50.                       int numItems,                                            // initial number of items
  51.                       FW_Boolean scrollVert = TRUE,                      // vertical scroll-bar
  52.                       const FW_CFont& font = FW_kNormalFont,
  53.                       FW_Message msg = FW_kListBoxDoubleClickedMsg,
  54.                       FW_Boolean singleSelection = TRUE,     
  55.                       FW_Boolean useFocusFrame = TRUE,                // outline for keyboard focus
  56.                       FW_Boolean useClientData = FALSE);           // extra 32bit value 
  57.  
  58. Then you can fill the list box with string items like in Form's method CFormView::CreateOwnSubViews:
  59.  
  60.       // ----- Create a list box and initialize some strings
  61.      FW_CListBox* listbox = FW_NEW(FW_CListBox, (ev, this, viewRect, kPlatformListBoxID, 
  62.                              10, true, helvetica, FW_kListBoxDoubleClickedMsg, false));
  63.      listbox->SetDrawingMode(ev, FALSE);
  64.      listbox->SetStringItem(ev, 1, FW_CString("Mac OS"));
  65.      listbox->SetStringItem(ev, 2, FW_CString("OS/2 Warp"));
  66.      ...
  67.      listbox->SetDrawingMode(ev, TRUE);
  68.  
  69. However it is easier to create the list box in resources, where the type FW_RListBox allows to initialize the strings at the same time.   Form’s resource file views.fr contains the following:
  70.  
  71.      FW_RListBox
  72.      (
  73.              kPlatformListBoxID,                      // view id
  74.              { FW_FIX(250),FW_FIX(362),FW_FIX(400),FW_FIX(440)},
  75.              FW_kFixedBounds,                            // binding
  76.              10,                                               // number of rows
  77.              1,                                                // vertical SB
  78.              0,                                                // single selection
  79.              1,                                                // use focus frame
  80.              0,                                                // don’t use clientdata
  81.              FW_kListBoxDoubleClickedMsg,          // DblClick message
  82.              FW_HELVETICA12,                             // font
  83.              {                                                 // List of strings
  84.                       "Mac OS",
  85.                       "OS/2 Warp",
  86.               ...
  87.              }
  88.      ),
  89.  
  90. List Box Attributes
  91.  
  92. The attributes used to create a list box are the following:
  93.  
  94. • A view id, required to be able to access this object later in your program.
  95.  
  96. • A bounds rectangle, placing the list box in its parent view.
  97.  
  98. • A binding flag.  It should be initialized to FW_kFixedBounds in order to keep the list box in a fixed position when its parent is resized.  You can change that by calling FW_CView::SetBindings or by using a different value in the resource.  
  99.  
  100. • An initial number of rows (or items).  You can change it later with AddStringItem or DeleteItems.  Rows not initialized with a string will be displayed empty.
  101. Note: do not use very large numbers!  The list box is limited to 32K of data which is equivalent to 1600 rows of 20 characters strings.
  102.  
  103. • A vertical scroll bar flag.  When true, or 1 in resources, the scroll bar is added during the list box creation, it cannot be added later.  The scroll bar belongs to the list box view, i.e. it is not an ODF scroll bar object.
  104.  
  105. • A selection mode.  When true, or 1 in resources, the list box is in single selection mode, the user can select only 1 item at a time.  When false, or 0 in resources, the user can select several items simultaneously in various ways (see the section on Keyboard Navigation).
  106.  
  107. • A focus frame flag.  When true, or 1 in resources, the list box is outlined by a frame when it has the keyboard focus.  You should keep this flag on except in cases where the list box is the only view which can accept the keyboard focus in your frame.
  108. Note: when the flag is true the list box rectangle is made smaller to leave space for the frame.  The view bounds are not changed.
  109.  
  110. • A client data flag.   When true, or 1 in resources, the list box is created with a second column made invisible.  Using  AddStringItem and SetStringItem you can store a 4 bytes “client data” value in this second column along with the string in the first column.  This is useful if you don’t want to rely on the item’s index in the list when the user makes a selection.  Instead of using the selected string or its index you can retrieve the client data value (which could be another index or a pointer) and perform the desired action.  However if the list is not shuffled by adding and removing items, the selected item index is good enough in most cases.
  111.  
  112. • A double-click message.  When not 0 the list box sends a FW_CListBoxNotification containing this message to its receiver objects to let them know which item has been double-clicked on.  You can use the predefined value FW_kListBoxDoubleClickedMsg or your own.
  113.  
  114. • A font object.  The class constructors use FW_kNormalFont by default which maps to Geneva 12 on Macintosh.  In resource you can use a macro such as FW_NORMAL_FONT defined in FWViews.fr or define your own macro at the top of the .fr file, such as:
  115.  
  116.      #define TIMES_12_BOLD    { FW_FIX(12), FW_kBold, "Times" }
  117.  
  118. • A list of strings.  In resources, you add a list of strings to initialize the list box, up to the number of rows declared above.  Strings are added in the same order.
  119.  
  120. Handling Double-Click Notifications
  121.  
  122. FW_CListBox views are also notifiers, they can send notifications to other objects in response to a double-click on an item. If your frame, or another object, is interested in these events you must declare it after the views creation.  It can be done in your CreateSubViews method, or your PostCreateViewFromStream method when using resources:
  123.  
  124.      FW_CListBox* listbox = (FW_CListBox*)FindViewById(ev, kPlatformListBoxID);
  125.     
  126.      frame->AddNotifier(listbox, FW_kListBoxDoubleClickedMsg);
  127.  
  128. Important: The message must be the same as the one used for creating the list box.  Also, your frame class must derive from FW_MReceiver.
  129.  
  130. Once this is done the frame can handle the list box notification as follows:
  131.  
  132.   void CFormFrame::HandleNotification(Environment* ev, 
  133.                                      const FW_CNotification& notification)
  134.   {
  135.        switch (notification.GetMessage()) 
  136.        {
  137.              case FW_kListBoxDoubleClickedMsg:
  138.              {
  139.                       const FW_CListBoxNotification& listBoxNotification = 
  140.                                                    (FW_CListBoxNotification&) notification;
  141.             
  142.                       // Beep if we double-click on the first item
  143.                       if (listBoxNotification.GetListBox(ev)->GetSelectedItem(ev) == 1)
  144.                                FW_Beep();
  145.              }
  146.              break;
  147.     ...
  148.  
  149. The cast of a notification object to FW_CListBoxNotification is safe because we know it’s a list box message.  Once you get the list box object with GetListBox  you can retrieve the selected item, check the list box id or take any other appropriate action.
  150.  
  151. See the Engineering note on Notifications for more information.        
  152.  
  153. Responding to Single-Click Selections
  154.  
  155. FW_CListBox objects don't send notifications in response to single-clicks or when the selection changes.  The mouse may be pressed on one item, moved and released on another one or released outside the list box.  The selection may change by using the keyboard or by program instead of  mouse clicks.
  156.  
  157. One way to detect mouse clicks is to implement a mouse click behavior as described later in this document.  Your program can then find out if the selection has changed and take appropriate action.   See FormView.cpp in the Form sample.
  158.  
  159. Tabbing Between List Boxes and Edit Views
  160.  
  161. List boxes and edit views can both receive the keyboard focus, i.e. become the frame’s target.  You can implement a tabbing behavior by creating an FW_CViewTabber object.  This cannot be done in resources in the current release, do it in your frame’s PostCreateViewFromStream method (or the CreateSubViews method if you are not using resources):
  162.  
  163.      // ----- Add a ViewTabber event handler to the frame 
  164.      fViewTabber = new FW_CViewTabber(ev, this); 
  165.  
  166. You must not delete this object in the frame’s destructor, it will be done for you because this is an attached event handler.
  167.  
  168. A frame containing this event handler traps the Tab key and selects the next view that wants to be the target (or the previous one if the Shift key was pressed at the same time).  The Tab key may be replaced by another key with the FW_CViewTabber::SetTabbingKey method.  The current tab key is returned by GetTabbingKey.
  169.  
  170. Note:  Dialog frames, instances derived from FW_CDialogFrame, have an FW_CViewTabber object already created for them.
  171.  
  172. Keyboard Navigation
  173.  
  174. A list box responds to Up and Down arrows, PageUp and PageDown, Home and End keys.
  175.  
  176. The following modifiers can be used to extend the selection in multi-selection mode:
  177.  
  178. • Shift-key: extends the selection continuously.
  179.  
  180. • Command-key: extends the selection discontinuously (with the mouse), or select the top item (Up arrow key), or select the bottom item (Down arrow key).
  181.  
  182. • Shift and Command keys together: select all items above (Up arrow key), or select all items below (Down arrow key)
  183.  
  184.  
  185. FW_CListBox Reference
  186.  
  187. Warning: in ODF the index values for list box items are between 1 and N, where N = GetCountItems(ev), not between 0 and N - 1 like in the Macintosh List Manager API.   Methods taking an index as an input argument will throw an assertion if you use an index that is out of range.
  188.  
  189. By default, the list box automatic drawing mode is on, all methods modifying the list box will update the screen if necessary.  You can use the SetDrawingMode method to disable this behavior temporarily.
  190.  
  191. Getting/Setting selected items
  192.  
  193. virtual void     SelectOneItem(Environment* ev, short index, 
  194.                                  FW_Boolean selected = true);
  195.  
  196. If selected is true this method deselects any selected item and selects item number index.  If selected is false, it deselects the item.
  197.     
  198. FW_Boolean     GetSelectedState(Environment* ev, short index) const;
  199.  
  200. This method returns whether item number index is selected or not.
  201.     
  202. short         GetSelectedItem(Environment* ev) const;
  203.  
  204. This method returns the index of the first selected item, or 0 it no item is selected.  If the list box allows multiple selections you must use the GetSelectionCount and GetSelectedItems to retrieve all selected items.
  205.     
  206. short         GetSelectionCount(Environment* ev) const;
  207.  
  208. This method returns the number of selected items, or 0 if no item is selected. 
  209.  
  210. short         GetSelectedItems(Environment* ev, short maxItems,    short* indexArray) const;
  211.  
  212. This method can be used only in multiple selection mode.  You pass maxItems, the number of items you want to get, and indexArray, an array of short integers of size maxItems.  The method returns a short value, numItems, which is the actual number of selected items found, and fills the array with the indices of the selected items from 1 to numItems.  If numItems is equal to maxItems there may be more selected items, use GetSelectionCount to get the exact number.
  213.  
  214. Adding/Changing/Deleting items
  215.  
  216. virtual void     SetStringItem(Environment* ev, short index,    
  217.                              const FW_CString& str);
  218.  
  219. Use this method to replace the string of the existing item number index.  The string must be less than 255 characters.
  220.  
  221. virtual void     SetStringItem(Environment* ev, short index, 
  222.                                                const FW_CString& str, void* clientData);
  223.  
  224. Use this method to replace the string the existing item number index and set its client data value at the same time (the list box must have been created with the Use Client Data attribute).  The string must be less than 255 characters.
  225.  
  226. virtual void     AddStringItem(Environment* ev, const FW_CString& str, 
  227.                                                short index = 0);
  228.  
  229. Use this method to add a new item to the list at position index, or at the end of the list if index is null.  The string must be less than 255 characters.
  230.  
  231. virtual void     AddStringItem(Environment* ev, const FW_CString& str, 
  232.                                                void* clientData, short index = 0);
  233.  
  234. Use this method to add a new item to the list at position index, or at the end of the list if index is null, and to set its client data value at the same time (the list box must have been created with the Use Client Data attribute).  The string must be less than 255 characters.
  235.  
  236. virtual void     DeleteItems(Environment* ev, short index, short count = 1);
  237.  
  238. This method removes count items from the list box, starting at position index.
  239.  
  240. Getting items
  241.  
  242. short          GetCountItems(Environment* ev) const;
  243.  
  244. This method returns the number of items in the list box.
  245.  
  246. FW_Boolean     GetStringItem(Environment* ev, short index, FW_CString& str) const;
  247.  
  248. This method returns the string stored at position index.  Its returned value is false if this item was empty, true otherwise.
  249.  
  250. FW_Boolean     GetStringItem(Environment* ev, short index, FW_CString& str, 
  251.                                                  void** clientData) const;
  252.  
  253. This method returns the string stored at position index in str and at the same time the clientData 4 bytes value  (the list box must have been created with the Use Client Data attribute).  Its returned value is false if there was no client data value associated with this item.
  254.  
  255. FW_Boolean     GetClientDataItem(Environment* ev, short index, 
  256.                                                       void** clientData) const;
  257.  
  258. This method returns the clientData 4 bytes value of item number index (the list box must have been created with the Use Client Data attribute).  Its returned value is false if there was no client data value associated with this item.
  259.  
  260. Utilities
  261.  
  262. FW_Boolean            GetDrawingMode(Environment* ev) const;
  263.  
  264. This method returns true is the automatic drawing mode is on, false otherwise. The drawing mode must be on in order for the list box to be updated.
  265.  
  266. virtual void        SetDrawingMode(Environment* ev, FW_Boolean draw);
  267.  
  268. This method turns the automatic drawing mode on or off.  You should turn it off only temporarily to avoid flashing during list box modifications.  After you turn it back on you must force an update of the view with Invalidate().
  269.  
  270.       listbox->SetDrawingMode(ev, FALSE);
  271.       listbox->SetStringItem(ev, 1, FW_CString("Mac OS"));
  272.       listbox->SetStringItem(ev, 2, FW_CString("OS/2 Warp"));
  273.       ...
  274.       listbox->SetDrawingMode(ev, TRUE);
  275.       listbox->Invalidate(ev);
  276.  
  277. virtual void         ScrollIntoView(Environment* ev, short index);
  278.  
  279. This method makes item number index  visible by scrolling the list box if necessary.
  280.  
  281. FW_PlatformHandle    GetPlatformListHandle(Environment* ev) const;
  282.  
  283. This method returns the native Macintosh handle to the list record in case you need more internal information.
  284.  
  285. Warning:  making direct List Manager calls may be dangerous.
  286.  
  287.  
  288. Adding More Features to FW_CListBox
  289.  
  290. Mouse Click Behavior
  291.  
  292. You don’t necessarily need to subclass FW_CListBox to customize a mouse-click action.  Using an event handler, or “behavior” object, allows you to do the same thing and avoids the need for a new resource type.  For example the Form sample implements a CMouseUpBehavior class to check if 1 or more items have been selected and enable a button accordingly.  See the file ODFDev:Form:Sources:FormView.cpp.
  293.  
  294. Content Model and Selections
  295.  
  296. If you decide to make a list box part of your content model you need to manage the presentation’s selection object as the user selects items and you need to externalize/internalize the list box data.  
  297.  
  298.  
  299. Miscellaneous Issues
  300.  
  301. Multiple Facets
  302.  
  303. When a list box view is visible in more than 1 facet you must force the redraw of all the other facets to see the correct update (i.e. the only facet updated by ODF is the active facet receiving keyboard events).  In particular there will be drawing problems if the list box spans across facet boundaries!
  304.  
  305. Multiple Frames
  306.  
  307. The list box content is local to the frame because it is stored by in the platform’s list box record.  If you open 2 frames of the same presentation, for example with the “View In Window” command, each frame contains its own list box and it is up to your part to maintain a common content when it makes sense to do so.
  308.  
  309.  
  310. © 1993 - 1996 Apple Computer, Inc. All rights reserved.
  311. Apple, the Apple Logo, Macintosh, and OpenDoc are trademarks of Apple Computer, Inc., registered in the United States and other countries.